package com.zenith.middleware.service.impl;

import com.zenith.common.result.PageResult;
import com.zenith.common.result.Result;
import com.zenith.common.constant.RedisKeyConstant;
import com.zenith.common.constant.RedisTtlConstant;
import com.zenith.middleware.feign.storage.StorageServiceFeignClient;
import com.zenith.middleware.po.dto.storage.ChunkCompleteDTO;
import com.zenith.middleware.po.dto.storage.ChunkInitDTO;
import com.zenith.middleware.po.dto.storage.ChunkUploadDTO;
import com.zenith.middleware.po.dto.storage.FileQueryDTO;
import com.zenith.middleware.po.dto.storage.FolderDTO;
import com.zenith.middleware.po.dto.storage.FolderFileQueryDTO;
import com.zenith.middleware.po.dto.storage.MoveFileDTO;
import com.zenith.middleware.po.dto.storage.ProviderDTO;
import com.zenith.middleware.po.dto.storage.RenameDTO;
import com.zenith.middleware.po.dto.storage.UploadInitDTO;
import com.zenith.middleware.po.vo.storage.ChunkInitVO;
import com.zenith.middleware.po.vo.storage.ChunkStatusVO;
import com.zenith.middleware.po.vo.storage.ChunkUploadVO;
import com.zenith.middleware.po.vo.storage.FileVO;
import com.zenith.middleware.po.vo.storage.FolderFileVO;
import com.zenith.middleware.po.vo.storage.FolderVO;
import com.zenith.middleware.po.vo.storage.StorageProviderVO;
import com.zenith.middleware.po.vo.storage.UploadInitVO;
import com.zenith.middleware.service.StorageService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 存储服务实现类
 */
@Slf4j
@Service
public class StorageServiceImpl implements StorageService {
    
    private final StorageServiceFeignClient storageServiceFeignClient;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    public StorageServiceImpl(StorageServiceFeignClient storageServiceFeignClient) {
        this.storageServiceFeignClient = storageServiceFeignClient;
    }
    
    // =========================== 分片上传相关接口 ===========================
    
    @Override
    public Result<ChunkInitVO> initChunkUpload(ChunkInitDTO chunkInitDTO) {
        Result<ChunkInitVO> result = storageServiceFeignClient.initChunkUpload(chunkInitDTO);
        // 清除相关缓存
        if (result != null && result.getData() != null) {
            clearChunkUploadCache();
        }
        return result;
    }

    /**
     * 上传分片
     */
    @Override
    public Result<ChunkUploadVO> uploadChunk(ChunkUploadDTO chunkUploadDTO) {
        Result<ChunkUploadVO> result = storageServiceFeignClient.uploadChunk(chunkUploadDTO);
        // 清除相关缓存
        if (result != null && result.getData() != null) {
            clearChunkUploadCache();
        }
        return result;
    }

    /**
     * 完成分片上传
     */
    @Override
    public Result<FileVO> completeChunkUpload(ChunkCompleteDTO chunkCompleteDTO) {
        Result<FileVO> result = storageServiceFeignClient.completeChunkUpload(chunkCompleteDTO);
        // 清除相关缓存
        if (result != null && result.getData() != null) {
            clearChunkUploadCache();
            clearFileListCache();
        }
        return result;
    }

    /**
     * 获取分片上传状态
     */
    @Override
    public Result<ChunkStatusVO> getChunkStatus(String uploadKey) {
        // 构建缓存键
        String cacheKey = "chunkStatus:" + uploadKey;
        
        // 尝试从缓存获取
        Result<ChunkStatusVO> cachedResult = (Result<ChunkStatusVO>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            log.info("从缓存获取分片上传状态数据: key={}", cacheKey);
            return cachedResult;
        }
        
        // 调用Feign客户端获取数据
        Result<ChunkStatusVO> result = storageServiceFeignClient.getChunkStatus(uploadKey);
        
        // 缓存结果
        if (result != null && result.getData() != null) {
            redisTemplate.opsForValue().set(cacheKey, result, RedisTtlConstant.DEFAULT_TTL, TimeUnit.SECONDS);
            log.info("缓存分片上传状态数据: key={}", cacheKey);
        }
        
        return result;
    }

    // =========================== 网盘功能相关接口 ===========================
    
    @Override
    public Result<FolderVO> createFolder(FolderDTO folderDTO) {
        Result<FolderVO> result = storageServiceFeignClient.createFolder(folderDTO);
        // 清除相关缓存
        if (result != null && result.getData() != null) {
            clearFolderTreeCache();
        }
        return result;
    }

    /**
     * 获取文件夹树
     */
    @Override
    public Result<List<FolderVO>> getFolderTree(Long userId) {
        // 构建缓存键
        String cacheKey = "folderTree:" + userId;
        
        // 尝试从缓存获取
        Result<List<FolderVO>> cachedResult = (Result<List<FolderVO>>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            log.info("从缓存获取文件夹树数据: key={}", cacheKey);
            return cachedResult;
        }
        
        // 调用Feign客户端获取数据
        Result<List<FolderVO>> result = storageServiceFeignClient.getFolderTree(userId);
        
        // 缓存结果
        if (result != null && result.getData() != null) {
            redisTemplate.opsForValue().set(cacheKey, result, RedisTtlConstant.DEFAULT_TTL, TimeUnit.SECONDS);
            log.info("缓存文件夹树数据: key={}", cacheKey);
        }
        
        return result;
    }

    /**
     * 获取文件夹中的文件列表
     */
    @Override
    public Result<PageResult<FolderFileVO>> getFolderFiles(FolderFileQueryDTO queryDTO) {
        // 构建缓存键
        String cacheKey = "folderFiles:" + queryDTO.getFolderId() + "_" + 
                         (queryDTO.getPageNum() != null ? queryDTO.getPageNum() : 1) + "_" + 
                         (queryDTO.getPageSize() != null ? queryDTO.getPageSize() : 10);
        
        // 尝试从缓存获取
        Result<PageResult<FolderFileVO>> cachedResult = (Result<PageResult<FolderFileVO>>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            log.info("从缓存获取文件夹文件列表数据: key={}", cacheKey);
            return cachedResult;
        }
        
        // 调用Feign客户端获取数据
        Result<PageResult<FolderFileVO>> result = storageServiceFeignClient.getFolderFiles(queryDTO);
        
        // 缓存结果
        if (result != null && result.getData() != null) {
            redisTemplate.opsForValue().set(cacheKey, result, RedisTtlConstant.DEFAULT_TTL, TimeUnit.SECONDS);
            log.info("缓存文件夹文件列表数据: key={}", cacheKey);
        }
        
        return result;
    }

    /**
     * 移动文件
     */
    @Override
    public Result<Boolean> moveFile(MoveFileDTO moveFileDTO) {
        Result<Boolean> result = storageServiceFeignClient.moveFile(moveFileDTO);
        // 清除相关缓存
        if (result != null && result.getData() != null && result.getData()) {
            clearFolderFilesCache();
            clearFileListCache();
        }
        return result;
    }

    /**
     * 重命名文件或文件夹
     */
    @Override
    public Result<Boolean> rename(RenameDTO renameDTO) {
        Result<Boolean> result = storageServiceFeignClient.rename(renameDTO);
        // 清除相关缓存
        if (result != null && result.getData() != null && result.getData()) {
            clearFolderFilesCache();
            clearFileListCache();
            clearFileDetailCache();
        }
        return result;
    }

    // =========================== 文件管理相关接口 ===========================
    
    @Override
    public Result<UploadInitVO> initUpload(UploadInitDTO uploadInitDTO) {
        return storageServiceFeignClient.initUpload(uploadInitDTO);
    }

    /**
     * 上传文件
     */
    @Override
    public Result<FileVO> uploadFile(MultipartFile file, Long fileId) {
        Result<FileVO> result = storageServiceFeignClient.uploadFile(file, fileId);
        // 清除相关缓存
        if (result != null && result.getData() != null) {
            clearFileListCache();
            clearFolderFilesCache();
        }
        return result;
    }

    /**
     * 下载文件
     */
    @Override
    public void downloadFile(Long fileId, HttpServletResponse response) {
        storageServiceFeignClient.downloadFile(fileId, response);
    }

    /**
     * 删除文件
     */
    @Override
    public Result<Boolean> deleteFile(Long fileId) {
        Result<Boolean> result = storageServiceFeignClient.deleteFile(fileId);
        // 清除相关缓存
        if (result != null && result.getData() != null && result.getData()) {
            clearFileListCache();
            clearFolderFilesCache();
            clearFileDetailCache();
        }
        return result;
    }

    /**
     * 获取文件详情
     */
    @Override
    public Result<FileVO> getFileDetail(Long fileId) {
        // 构建缓存键
        String cacheKey = RedisKeyConstant.FILE_INFO + fileId;
        
        // 尝试从缓存获取
        Result<FileVO> cachedResult = (Result<FileVO>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            log.info("从缓存获取文件详情数据: key={}", cacheKey);
            return cachedResult;
        }
        
        // 调用Feign客户端获取数据
        Result<FileVO> result = storageServiceFeignClient.getFileDetail(fileId);
        
        // 缓存结果
        if (result != null && result.getData() != null) {
            redisTemplate.opsForValue().set(cacheKey, result, RedisTtlConstant.FILE_INFO_TTL, TimeUnit.SECONDS);
            log.info("缓存文件详情数据: key={}", cacheKey);
        }
        
        return result;
    }

    /**
     * 分页查询文件列表
     */
    @Override
    public Result<PageResult<FileVO>> listFiles(FileQueryDTO queryDTO) {
        // 构建缓存键
        String cacheKey = RedisKeyConstant.FILE_LIST + (queryDTO.getPageNum() != null ? queryDTO.getPageNum() : 1) + "_" + 
                         (queryDTO.getPageSize() != null ? queryDTO.getPageSize() : 10);
        
        // 尝试从缓存获取
        Result<PageResult<FileVO>> cachedResult = (Result<PageResult<FileVO>>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            log.info("从缓存获取文件列表数据: key={}", cacheKey);
            return cachedResult;
        }
        
        // 调用Feign客户端获取数据
        Result<PageResult<FileVO>> result = storageServiceFeignClient.listFiles(queryDTO);
        
        // 缓存结果
        if (result != null && result.getData() != null) {
            redisTemplate.opsForValue().set(cacheKey, result, RedisTtlConstant.FILE_LIST_TTL, TimeUnit.SECONDS);
            log.info("缓存文件列表数据: key={}", cacheKey);
        }
        
        return result;
    }

    // =========================== 存储提供商相关接口 ===========================
    
    /**
     * 获取所有存储提供商列表
     */
    @Override
    public Result<List<StorageProviderVO>> listProviders() {
        // 构建缓存键
        String cacheKey = "providerList";
        
        // 尝试从缓存获取
        Result<List<StorageProviderVO>> cachedResult = (Result<List<StorageProviderVO>>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            log.info("从缓存获取存储提供商列表数据: key={}", cacheKey);
            return cachedResult;
        }
        
        // 调用Feign客户端获取数据
        Result<List<StorageProviderVO>> result = storageServiceFeignClient.listProviders();
        
        // 缓存结果
        if (result != null && result.getData() != null) {
            redisTemplate.opsForValue().set(cacheKey, result, RedisTtlConstant.DEFAULT_TTL, TimeUnit.SECONDS);
            log.info("缓存存储提供商列表数据: key={}", cacheKey);
        }
        
        return result;
    }

    /**
     * 添加存储提供商
     */
    @Override
    public Result<Boolean> addProvider(ProviderDTO providerDTO) {
        Result<Boolean> result = storageServiceFeignClient.addProvider(providerDTO);
        // 清除相关缓存
        if (result != null && result.getData() != null && result.getData()) {
            clearProviderCache();
        }
        return result;
    }

    /**
     * 更新存储提供商
     */
    @Override
    public Result<Boolean> updateProvider(ProviderDTO providerDTO) {
        Result<Boolean> result = storageServiceFeignClient.updateProvider(providerDTO);
        // 清除相关缓存
        if (result != null && result.getData() != null && result.getData()) {
            clearProviderCache();
        }
        return result;
    }

    /**
     * 删除存储提供商
     */
    @Override
    public Result<Boolean> deleteProvider(Long id) {
        Result<Boolean> result = storageServiceFeignClient.deleteProvider(id);
        // 清除相关缓存
        if (result != null && result.getData() != null && result.getData()) {
            clearProviderCache();
        }
        return result;
    }

    /**
     * 设置默认存储提供商
     */
    @Override
    public Result<Boolean> setDefaultProvider(Long id) {
        Result<Boolean> result = storageServiceFeignClient.setDefaultProvider(id);
        // 清除相关缓存
        if (result != null && result.getData() != null && result.getData()) {
            clearDefaultProviderCache();
        }
        return result;
    }

    /**
     * 获取默认存储提供商
     */
    @Override
    public Result<StorageProviderVO> getDefaultProvider() {
        // 构建缓存键
        String cacheKey = "defaultProvider";
        
        // 尝试从缓存获取
        Result<StorageProviderVO> cachedResult = (Result<StorageProviderVO>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            log.info("从缓存获取默认存储提供商数据: key={}", cacheKey);
            return cachedResult;
        }
        
        // 调用Feign客户端获取数据
        Result<StorageProviderVO> result = storageServiceFeignClient.getDefaultProvider();
        
        // 缓存结果
        if (result != null && result.getData() != null) {
            redisTemplate.opsForValue().set(cacheKey, result, RedisTtlConstant.DEFAULT_TTL, TimeUnit.SECONDS);
            log.info("缓存默认存储提供商数据: key={}", cacheKey);
        }
        
        return result;
    }
    
    // =========================== 缓存清理方法 ===========================
    
    /**
     * 清除分片上传相关缓存
     */
    private void clearChunkUploadCache() {
        redisTemplate.delete("chunkUpload:*");
        redisTemplate.delete("chunkStatus:*");
        log.info("清除分片上传相关缓存");
    }
    
    /**
     * 清除文件夹树相关缓存
     */
    private void clearFolderTreeCache() {
        redisTemplate.delete("folderTree:*");
        log.info("清除文件夹树相关缓存");
    }
    
    /**
     * 清除文件夹文件相关缓存
     */
    private void clearFolderFilesCache() {
        redisTemplate.delete("folderFiles:*");
        log.info("清除文件夹文件相关缓存");
    }
    
    /**
     * 清除文件列表相关缓存
     */
    private void clearFileListCache() {
        redisTemplate.delete(RedisKeyConstant.FILE_LIST + "*");
        log.info("清除文件列表相关缓存");
    }
    
    /**
     * 清除文件详情相关缓存
     */
    private void clearFileDetailCache() {
        redisTemplate.delete(RedisKeyConstant.FILE_INFO + "*");
        log.info("清除文件详情相关缓存");
    }
    
    /**
     * 清除存储提供商相关缓存
     */
    private void clearProviderCache() {
        redisTemplate.delete("providerList");
        redisTemplate.delete("defaultProvider");
        log.info("清除存储提供商相关缓存");
    }
    
    /**
     * 清除默认存储提供商相关缓存
     */
    private void clearDefaultProviderCache() {
        redisTemplate.delete("defaultProvider");
        log.info("清除默认存储提供商相关缓存");
    }
}